﻿using System;
using System.Collections.Generic;
using DotNetNeural.Data.Base;

namespace DotNetNeural.Data.Learning
{
    public class TrainingSetIterator : Iterator<TrainingSetItem>
    {
        #region Properties

        public bool NavigateControlItems { get; private set; }

        #endregion

        public TrainingSetIterator(ITrainingSet trainingSet)
            : this(trainingSet, false) { }

        public TrainingSetIterator(ITrainingSet trainingSet, bool useControlItems)
        {
            if (trainingSet == null)
                throw new NullReferenceException("Illegal null-reference training set");

            this.trainingSet = trainingSet;
            NavigateControlItems = useControlItems;

            MoveFirst();
        }

        #region Iterator<TrainingSetItem> Members

        public bool IsLast { get; private set; }

        public TrainingSetItem Value { get; private set; }

        public void MoveFirst()
        {
            Init();
        }

        public bool MoveNext()
        {
            /*
             * Remove first element in collection
             */

            currentCollection.RemoveAt(previousIndex);

            UpdateIsLast();

            if (IsLast)
            {
                Value = null;
                return false;
            }
            else
            {
                Value = GetRandomItem();
                return true;
            }
        }

        #endregion

        #region Private methods

        private void Init()
        {
            if (NavigateControlItems)
                currentCollection = new List<TrainingSetItem>(trainingSet.ControlItems);
            else
                currentCollection = new List<TrainingSetItem>(trainingSet.LearningItems);

            UpdateIsLast();
            rnd = new Random(Environment.TickCount);

            if (IsLast)
                Value = null;
            else
            {
                Value = GetRandomItem();
            }
        }

        private void UpdateIsLast()
        {
            IsLast = currentCollection.Count == 0;
        }

        private TrainingSetItem GetRandomItem()
        {
            previousIndex = rnd.Next(0, currentCollection.Count);
            return currentCollection[previousIndex];
        }

        #endregion

        #region Private fields

        private ITrainingSet trainingSet;
        private List<TrainingSetItem> currentCollection;
        private Random rnd;
        private int previousIndex = 0;

        #endregion

    }
}
